/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Animated Line Control Class
 *      A line control like the animated bar on Windows Startup.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Text;
using System.ComponentModel;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Timers;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// A line control like the animated bar on Windows Startup.
    /// </summary>
    [Browsable(true), ToolboxItem(true), DesignerCategory("UserControl")]
    public partial class AnimatedLine  : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Constants Declarations
         *------------------------------------------------------------------------------*/
        #region Private Constants Declarations
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
		private Color _mainColor;
		private Color _animationColor;
        private System.Timers.Timer _timer;
        private Graphics _graphicsRef;

		private int _position = 0;
		private int _width = 0;
		private int _height = 0;
		private bool _busy = false;
		private bool _stopping = false;

        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public AnimatedLine()
            : base()
        {
            InitializeComponent();
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
                if (_timer != null)
                    _timer.Dispose();
            }

            _timer = null;
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Hidden Properties
         *------------------------------------------------------------------------------*/
        #region Hidden Properties
        [Browsable(false)]
        private new string Text
        {
            get { return string.Empty; }
            set { base.Text = string.Empty; }
        }
        [Browsable(false)]
        internal new bool TabStop
        {
            get { return false; }
            set { base.TabStop = false; }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the main background color of the animated line.
        /// </summary>
        /// <value>
        /// The <see cref="Color"/> of the line.
        /// </value>
        public Color LineColor
        {
            get { return _mainColor; }
            set
            {
                base.BackColor = value;
                _mainColor = value;
                UpdateControl();
            }
        }
        /// <summary>
        /// Gets or sets the color that moves through the line.
        /// </summary>
        /// <value>
        /// The <see cref="Color"/> that is the animated portion of the line.
        /// </value>
        public Color AnimationColor
        {
            get { return _animationColor; }
            set
            {
                _animationColor = value;
                UpdateControl();
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Adjusts the size of the control and fires the <see cref="System.Windows.Forms.UserControl.Load"/> event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            _height = Height + 2;
            _width = (int)(Width / 4);
        }
        /// <summary>
        /// Paints the control and fires the <see cref="Control.Paint"/> event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            Render(e.Graphics);
            base.OnPaint(e);

        }
        /// <summary>
        /// Adjusts the size of the control and fires the <see cref="Control.Resize"/> event.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            _height = Height + 2;
            _width = (int)((float)Width / 4);
            UpdateControl();
        }
        /// <summary>
        /// Creates and assigns the event handlers for the items contained within the control.
        /// </summary>
        protected override void AssignEventHandlers()
        {
        }
        /// <summary>
        /// Removes the event handlers for the items contained within the control.
        /// </summary>
        protected override void RemoveEventHandlers()
        {
        }
        /// <summary>
        /// Initializes the content of the control before the event handlers are assigned.
        /// </summary>
        protected override void InitializeContent()
        {
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl()"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        protected override void UpdateCurrentControlContents()
        {
            if (_graphicsRef == null)
                _graphicsRef = CreateGraphics();

            Render(_graphicsRef);
            _graphicsRef.Dispose();
            _graphicsRef = null;
        }
        /// <summary>
        /// This method is invoked in the main UI thread to perform any neccessary
        /// updates to the UI.
        /// </summary>
        /// <remarks>
        /// Calling the related <see cref="AdaptiveControlBase.UpdateControl(object[])"/> is used to prevent illegal 
        /// cross-threaded UI update calls.
        /// </remarks>
        /// <param name="data">
        /// The data supplied to the control to update the internal controls with.
        /// </param>
        protected override void UpdateCurrentControlContents(object[] data)
        {
            UpdateCurrentControlContents();
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Starts the animation on the control.
        /// </summary>
        public void Activate()
        {
            _stopping = false;
            if (_timer == null)
            {
                _timer = new System.Timers.Timer();
                _timer.Interval = 15;
                _timer.Elapsed += new System.Timers.ElapsedEventHandler(WorkerThread);
                _timer.Start();
            }
        }
        /// <summary>
        /// Refreshes and re-draws the control.
        /// </summary>
        public override void Refresh()
        {
            UpdateControl();
        }
        /// <summary>
        /// Stops the animation on the control.
        /// </summary>
        public void Deactivate()
        {
            _stopping = true;
            if (_timer != null)
            {
                _timer.Elapsed += new System.Timers.ElapsedEventHandler(WorkerThread);
                _timer.Stop();
                _timer.Dispose();
            }
            _timer = null;
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Renders the item.
        /// </summary>
        private void Render(Graphics g)
        {
            int x = 0;
            Rectangle rect;

            if ((g != null) && (!_busy))
            {
                _busy = true;
                rect = new Rectangle(0, 0, Width, Height);
                g.Clip = new Region(rect);

                try
                {
                    x = _position + _width;
                    GraphicsTasks.DrawGradientRectangle(g, new Rectangle(x, -1, _width + 5, _height), _animationColor, _mainColor, LinearGradientMode.Horizontal);
                    GraphicsTasks.DrawGradientRectangle(g, new Rectangle(_position, -1, _width + 5, _height), _mainColor, _animationColor, LinearGradientMode.Horizontal);
                    GraphicsTasks.DrawLine(g, _position, -1, 1, _height, BackColor);
                    if (x + _width > Width)
                    {
                        x = 0 - (Width - x);
                        GraphicsTasks.DrawGradientRectangle(g, new Rectangle(x - 5, -1, _width + 1, _height), _animationColor, _mainColor, LinearGradientMode.Horizontal);
                        GraphicsTasks.DrawGradientRectangle(g, new Rectangle(x - _width, -1, _width + 1, _height), _mainColor, _animationColor, LinearGradientMode.Horizontal);
                    }
                }
                catch (Exception)
                {
                    x = 0;
                }
                _busy = false;
            }
        }
        private void WorkerThread(object sender, ElapsedEventArgs e)
        {
            _position += 2;
            if (_position > Width)
                _position = 0;

            if (!_stopping)
                UpdateControl();

        }
        #endregion

    }
}
